package com.bsoft.client.proxy;

import com.bsoft.client.common.RequestMetadata;
import com.bsoft.client.transport.RpcTransportFactory;
import com.bsoft.core.common.RpcRequest;
import com.bsoft.core.common.RpcResponse;
import com.bsoft.core.protocol.MessageHeader;
import com.bsoft.core.protocol.MessageProtocol;
import com.bsoft.core.serialization.SerializationType;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 通过JDK，为接口生成代理类
 */
public class JDKRpcProxy implements RpcProxy{
    @Override
    public <T> T proxyInterface(RequestMetadata metadata, Class<T> serviceInterface) {
        JDKProxyHandler proxyHandler = new JDKProxyHandler(serviceInterface, metadata);
        return (T)Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, proxyHandler);
    }

    public class JDKProxyHandler implements InvocationHandler{

        private Class<?> clazz;
        private String address;
        private int port;
        private SerializationType serializationType;

        public JDKProxyHandler(Class<?> clazz, RequestMetadata metadata) {
            this.clazz = clazz;
            this.address = metadata.getAddress();
            this.port = metadata.getPort();
            this.serializationType = metadata.getSerializationType();
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 组装消息体
            RpcRequest message = new RpcRequest();
            message.setServiceName(this.clazz.getName());
            message.setMethodName(method.getName());
            message.setParameterTypes(method.getParameterTypes());
            message.setParameters(args);

            // 组装协议
            MessageProtocol<RpcRequest> protocol = new MessageProtocol<>();
            protocol.setBody(message);
            MessageHeader header = MessageHeader.build(serializationType.name());
            protocol.setHeader(header);

            // 组装元数据
            RequestMetadata metadata = RequestMetadata.builder()
                    .address(address)
                    .port(port)
                    .protocol(protocol)
                    .build();
            // 获取传输通道
            MessageProtocol<RpcResponse> response = RpcTransportFactory.getDefaultTransportInstance().send(metadata);
            return response.getBody().getData();
        }
    }
}
